[!NOTE]
本系列文章已進行全域去敏與匿名化處理,專案代號統一為DataGateway,內網 IP 統一為10.0.0.x。
在前面的章節中,我們已經成功利用 ConfigFS 騙過了 Windows 電腦,讓它以為插上來的是一顆「隨身碟」(Mass Storage Device)。
但在 Windows 端看到隨身碟跳出來,並不代表你可以存取資料。如果沒有提供儲存空間,Windows 會殘酷地跳出:「請插入磁片」或「磁碟未格式化」。
我們需要餵給這顆「隨身碟」一個實際存在的儲存空間。但問題來了,Raspberry Pi 只有一張 SD 卡(檔案系統是 ext4),我們總不能把整張作業系統的 SD 卡直接掛給 Windows 讀取吧?Windows 原生根本不認識 ext4!
因此,我們需要第三階段的核心技術:虛擬磁碟 (Virtual Disk Image)。
在醫療邊緣設備的場景中,護理師或醫生會把 DataGateway 從感測器端拔下來,然後插上護理站的 Windows 電腦來讀取裡面的 CSV 報表。
為了確保相容性,這個 USB 空間必須是 Windows 原生支援的格式,最通用的選擇就是 FAT32。
我們的策略是:在 Raspberry Pi 的 ext4 檔案系統內,建立一個巨大的「檔案」,然後把這個「檔案」當作一塊空白硬碟,將它格式化成 FAT32,最後把這塊「檔案」餵給 USB Gadget 的 LUN (Logical Unit Number)。
這聽起來很像虛擬機 (VM) 的虛擬硬碟檔 (.vdi 或 .vmdk) 對吧?沒錯,概念完全一樣!
dd 指令無中生有Linux 有一個古老且威力強大的工具叫做 dd (Data Duplicator,也有人戲稱它叫 Disk Destroyer)。它可以用來位元對位元地複製資料。
我們要用它從 /dev/zero (這是一個會無限吐出 0x00 的特殊設備) 抓取資料,寫入到我們指定的路徑,藉此「撐」出一個指定大小的實體檔案。
# 在 /opt/gateway 目錄下,建立一個名為 usb_disk.img 的檔案
# bs=1M (每次寫入 1MB)
# count=256 (寫入 256 次)
# 最終會產生一個 256MB 的空白檔案
sudo dd if=/dev/zero of=/opt/gateway/usb_disk.img bs=1M count=256
執行完畢後,用 ls -lh 觀察,你會看到一個扎扎實實佔用 256MB 空間的 usb_disk.img。
這就是我們的「實體硬碟」了,只是它現在裡面全是 0x00,什麼格式都沒有。
mkdosfs 格式化為 FAT32接下來,我們要對這顆剛出廠的「空白硬碟」進行格式化。
因為 Windows 認得 FAT32,所以我們需要安裝 dosfstools:
sudo apt-get update
sudo apt-get install dosfstools -y
接著,使用 mkdosfs (或是 mkfs.vfat) 直接對這個 .img 檔案進行格式化。
[!WARNING]
通常格式化指令是針對/dev/sda1這種磁區 (Partition),但 Linux 強大的地方就在於,它允許你直接對一般檔案進行格式化!
# -F 32 : 指定格式為 FAT32
# -I : 強制對整個裝置 (不分區) 進行格式化
# -n : 設定磁碟區標籤 (Volume Label) 為 DATADOCK
sudo mkdosfs -F 32 -I -n "DATADOCK" /opt/gateway/usb_disk.img
執行完畢後,這顆 usb_disk.img 已經不是一個普通的檔案了,它內部現在擁有完整的 FAT32 檔案分配表 (File Allocation Table) 結構!
回到我們 Day 10 寫的 ConfigFS 腳本。在 Mass Storage 的 LUN 設定中,我們要把剛剛做好的 usb_disk.img 綁定進去:
# 假設你已經建立好 mass_storage.0
cd /sys/kernel/config/usb_gadget/gateway_gadget/functions/mass_storage.0
# 將 img 檔案的路徑寫入 LUN 0 的 file 屬性中
echo "/opt/gateway/usb_disk.img" > lun.0/file
# 確保它是不可移除的唯讀/讀寫隨身碟 (視你的設計而定)
echo 0 > lun.0/removable
echo 0 > lun.0/cdrom
只要確保這一切都在 Day 13 提到的 echo UDC_NAME > UDC (點火) 之前完成即可。
現在,如果你把 Raspberry Pi 透過 Type-C 連接線插上 Windows 電腦,Windows 就會發出清脆的「登愣」聲,並且彈出一個名為 DATADOCK 的 256MB 隨身碟!
這感覺非常神奇,我們用純軟體的方式,在樹莓派裡憑空捏出了一個隨身碟給 PC 讀取。
但是,危機也在此刻埋下。
如果 Windows 正在讀取這顆 FAT32 磁碟,那 Raspberry Pi 內部的 Python 程式該怎麼把 Edge Sensor 的最新感測資料寫進這個 FAT32 空間裡呢?
我們總不能讓 Pi 和 Windows 同時對同一個 FAT32 結構進行寫入吧?
這就是邊緣儲存設備最令人聞風喪膽的 雙腦分裂 (Split-Brain) 問題。
為了解決這個問題,明天我們必須先學習 Linux 黑魔法中的黑魔法:Loop Device (losetup)。